package comgame.components;

import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.component.Component;
import com.almasb.fxgl.texture.Texture;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;

/**
 * HealthComponent 类用于管理游戏实体的血量系统。
 * 包含血量值、UI 显示以及响应血量变化的功能。
 */
public class HealthComponent extends Component {
    /**
     * 最大血量属性，默认为 100。
     */
    private IntegerProperty maxHealth = new SimpleIntegerProperty(100);

    /**
     * 当前血量属性，初始值与最大血量一致。
     */
    private IntegerProperty currentHealth = new SimpleIntegerProperty(maxHealth.get());

    /**
     * 默认心形图标纹理（未缩放）。
     */
    Texture heart = FXGL.getAssetLoader().loadTexture("heart.png");

    /**
     * 血量显示的 UI 容器。
     */
    private StackPane healthDisplay;

    /**
     * 缩放后的心形图标纹理（16x16）。
     */
    private Texture heartIcon;

    /**
     * 显示当前血量和最大血量的文本。
     */
    private Text healthText;

    /**
     * 血量文本的背景框，带边框和圆角。
     */
    private Rectangle backgroundBox;

    /**
     * 构造函数，设置双向绑定以确保 currentHealth 和 maxHealth 初始值一致。
     */
    public HealthComponent() {
        currentHealth.set(maxHealth.get());
    }

    public StackPane getHealthDisplay() {
        return healthDisplay;
    }
    /**
     * 当组件被添加到实体时调用，初始化血量 UI。
     */
    @Override
    public void onAdded() {
        createHealthDisplay();
    }

    /**
     * 创建血量显示 UI 并将其添加到实体视图中。
     */
    private void createHealthDisplay() {
        // 加载并缩放心形图标
        heartIcon = FXGL.getAssetLoader().loadTexture("heart.png", 16, 16);

        // 初始化血量文本样式
        healthText = new Text();
        healthText.setFont(Font.font(14));
        healthText.setFill(Color.BLACK);

        // 创建背景框并设置样式
        backgroundBox = new Rectangle();
        backgroundBox.setFill(Color.WHITE);
        backgroundBox.setStroke(Color.BLACK);
        backgroundBox.setStrokeWidth(1.5);
        backgroundBox.setArcWidth(5);
        backgroundBox.setArcHeight(5);

        // 创建水平布局容器并居中对齐
        HBox content = new HBox(5, heartIcon, healthText);
        content.setAlignment(Pos.CENTER);

        // 使用 StackPane 将背景框和内容组合在一起
        healthDisplay = new StackPane(backgroundBox, content);
        healthDisplay.setAlignment(Pos.CENTER);

        // 设置内容内边距
        StackPane.setMargin(content, new Insets(3, 8, 3, 8));

        // 设置血条位置在实体上方
        healthDisplay.setTranslateY(-35);

        // 将血条添加到实体的视图中
        entity.getViewComponent().addChild(healthDisplay);

        // 监听血量变化以更新 UI
        currentHealth.addListener((obs, old, newHealth) -> {
            updateHealthDisplay();
        });

        // 初始更新血量显示
        updateHealthDisplay();
    }

    /**
     * 更新血量显示文本及背景框大小。
     */
    private void updateHealthDisplay() {
        healthText.setText(currentHealth.get() + "/" + maxHealth.get());

        // 根据文本宽度动态调整背景框大小
        double width = healthText.getLayoutBounds().getWidth() + 40;
        backgroundBox.setWidth(width);
        backgroundBox.setHeight(25);
    }

    /**
     * 每帧更新血条的位置，使其始终位于实体正上方。
     */
    @Override
    public void onUpdate(double tpf) {
        if (entity != null && healthDisplay != null) {
            double centerX = entity.getWidth() / 2 - healthDisplay.getBoundsInLocal().getWidth() / 2;
            healthDisplay.setTranslateX(centerX);
        }
    }

    /**
     * 受到伤害，减少当前血量。
     * @param amount 伤害数值。
     */
    public void takeDamage(int amount) {
        currentHealth.set(Math.max(0, currentHealth.get() - amount));
    }

    /**
     * 恢复血量。
     * @param amount 恢复数值。
     */
    public void heal(int amount) {
        currentHealth.set(Math.min(maxHealth.get(), currentHealth.get() + amount));
    }

    /**
     * 获取当前血量值。
     * @return 当前血量。
     */
    public int getHealth() {
        return currentHealth.get();
    }

    /**
     * 获取当前血量属性。
     * @return IntegerProperty 类型的当前血量。
     */
    public IntegerProperty currentHealthProperty() {
        return currentHealth;
    }

    /**
     * 获取最大血量值。
     * @return 最大血量。
     */
    public int getMaxHealth() {
        return maxHealth.get();
    }

    /**
     * 获取最大血量属性。
     * @return IntegerProperty 类型的最大血量。
     */
    public IntegerProperty maxHealthProperty() {
        return maxHealth;
    }

    /**
     * 设置新的最大血量，并调整当前血量不超过新上限。
     * @param maxHealth 新的最大血量。
     */
    public void setMaxHealth(int maxHealth) {
        this.maxHealth.set(maxHealth);
        if (currentHealth.get() > maxHealth) {
            currentHealth.set(maxHealth);
            restoreFullHealth();
        }
    }

    /**
     * 设置当前血量。
     * @param health 新的当前血量。
     */
    public void setHealth(int health) {
        this.currentHealth.set(health);
    }
    
    /**
     * 完全恢复血量到最大值。
     */
    public void restoreFullHealth() {
        this.currentHealth.set(this.maxHealth.get());
    }
}
